//
//  CS_ImportMusicRequest.swift
//  NewSS
//
//  Created by 杨馥瑞 on 2021/11/3.
//

import UIKit
import HandyJSON
import XCGLogger

enum CS_MusicListType: Int {
    case hot = 0
    case my = 1
}

class CS_ImportMusicRequest {
    
    /// 获取歌单列表，存在数据库中，并且已经下载过，有音乐文件
    static func fetchHadAddMusicListComplete(_ complete: @escaping ([CS_MusicModel])->Void) {
        let musics = CS_MusicManager.shared.queryAllMusics()
        DispatchQueue.main.async {
            complete(musics)
        }
    }
    
    static func fetchLocalMusicListDbComplete(_ complete: ([CS_MusicModel])->Void, netComplete: (([CS_MusicModel])->Void)?) {
        let musics = CS_MusicManager.shared.queryAllMusics()
        complete(musics)
        
        if netComplete != nil {
            let musicTrackIds = musics.map { $0.musicTrackId }
            let musicTrackIdSet = Set(musicTrackIds)
            
            fetchMusicListFromRemote(withMusicListType: .my, pageKey: "", pageLimit: 0) { musicList in
                guard let musicList = musicList else { return }
                var needSaveMusics = [CS_MusicModel]()
                for music in musicList {
                    if music.fileExist && !musicTrackIdSet.contains(music.musicTrackId) {
                        // 已经下载好，且数据库不存在，保存该数据
                        needSaveMusics.append(music)
                    }
                }
                CS_MusicManager.shared.addMusicArray(needSaveMusics)
                let result = CS_MusicManager.shared.queryAllMusics()
                netComplete?(result)
            }
        }
    }
    
    
    /// 精选列表
    static func fetchHotMusicListFromRemote(_ completion: @escaping ([CS_MusicModel]?)->Void) {
        fetchMusicListFromRemote(withMusicListType: .hot, pageKey: "", pageLimit: 0) { musicList in
            completion(musicList)
        }
    }
    
    /// 根据 listType 获取音乐列表
    static func fetchMusicListFromRemote(withMusicListType listType: CS_MusicListType, pageKey: String, pageLimit: Int,  _ completion: @escaping ([CS_MusicModel]?)->Void) {
        let params: [String : Any] = [
            "type" : listType.rawValue,
            "pg_key" : pageKey,
            "limit" : pageLimit
        ]
        HttpManager.shared.GET(kLiveGetMusicListUrl, params: params).success { (json) in
            var result = [CS_MusicModel]()
            json["tracks"].arrayObject?.forEach {
                if let musicDic = $0 as? [String : Any], let music = CS_MusicModel.getMusicModelWithDict(musicDic) {
                    music.isLocal = false
                    result.append(music)
                }
            }
            completion(result)
        }.failed { (errCode, errMsg) in
            completion(nil)
        }
    }
    
    /// 搜索音乐
    static func searchMusic(_ keyword: String, _ completion: @escaping ([CS_MusicModel]?)->Void, cancel: (()->Void)?) {
        searchMusic(start: 0, count: 15, keyword: keyword) { keywordFromCallback, musicList in
            if keyword == keywordFromCallback {
                completion(musicList)
            }
            else {
                cancel?()
            }
        }
    }
    
    /// 搜索音乐
    static func searchMusic(start: Int, count: Int, keyword: String, _ completion: @escaping (String, [CS_MusicModel]?)->Void)  {
        let params: [String : Any] = [
            "start" : start,
            "count" : count,
            "keyword" : keyword
        ]
        HttpManager.shared.GET(kLiveSearchMusicUrl, params: params, cacheDuration: 600, timeoutInterval: 10).success { (json) in
            var result = [CS_MusicModel]()
            json["results"].arrayObject?.forEach {
                if let trackDic = $0 as? [String : [String : Any]], let music = CS_MusicModel.getMusicModelWithDict(trackDic["track"]) {
                    music.isLocal = false
                    result.append(music)
                }
            }
            completion(keyword, result)
        }.failed { (errCode, errMsg) in
            completion(keyword, nil)
        }
    }
    
    /// 是否已下载
    static func musicIsDownloaded(_ music: CS_MusicModel) -> Bool {
        return CS_AccompanyManager.shardInstance.isMusicDownload(music)
    }
    
    /// 是否正在下载
    static func musicIsDownloading(_ music: CS_MusicModel) -> Bool {
        return musicToTimer.keys.contains(music.musicTrackId)
    }
    
    private static let kDownloadTimeMax: TimeInterval = 300 // 300秒下载超时限制
    private static var musicToTimer = [Int : Timer]()
    /// [musicTrackId : 时间戳]
    private static var musicToStartTime = [Int : TimeInterval]()
    
    /// 下载音乐
    static func downloadMusic(_ music: CS_MusicModel, progressBlock: ((CGFloat)->Void)?, complete: @escaping (Bool)->Void) {
        CJAssert(Thread.isMainThread)
        guard musicToTimer[music.musicTrackId] == nil else {
            // 已经在队列里
            return
        }
        let doFinishBlock: ((Bool)->Void)? = { isSuccess in
            // 添加到歌单
            if isSuccess {
                music.isAdded = true
                music.identifier = music.getIdentifier()
                CS_MusicManager.shared.addMusic(music)
            }
            complete(isSuccess)
        }
        CS_AccompanyManager.shardInstance.recordMusic(music) // 加入下载队列
        musicToStartTime[music.musicTrackId] = Date().timeIntervalSince1970
        let timer = Timer.ik_scheduledTimer(withTimeInterval: 0.1, repeats: true) {
            
            func removeTask(_ music: CS_MusicModel) {
                let c_timer = musicToTimer[music.musicTrackId]
                c_timer?.invalidate()
                musicToTimer.removeValue(forKey: music.musicTrackId)
                musicToStartTime.removeValue(forKey: music.musicTrackId)
            }
            
            let progress = CS_AccompanyManager.shardInstance.getMusicDownloadProgress(music)
            if progress < 1.0 {
                let startTime = self.musicToStartTime[music.musicTrackId] ?? 0
                let useTime = Date().timeIntervalSince1970 - startTime
                if useTime > kDownloadTimeMax {
                    // 下载超时
                    doFinishBlock?(false)
                    removeTask(music)
                }
                else {
                    progressBlock?(progress)
                }
            }
            else {
                doFinishBlock?(true)
                removeTask(music)
            }
        }
        if let timer = timer {
            self.musicToTimer[music.musicTrackId] = timer
        }
    }
    
    /// 获取音乐文件路径
    static func getMusicFilePath(from music: CS_MusicModel) -> String {
        return CS_AccompanyManager.shardInstance.getAudioLocalPath(from: music)
    }
    
}
